//    Copyright (C) Kherty.  All rights reserved.
using System;
using System.ComponentModel;
using System.Diagnostics.Contracts;
using System.Reflection;
using System.Text;
using OpenLS.Spreadsheet.Expressions;
using OpenLS.Spreadsheet.Parsing;

namespace OpenLS.Spreadsheet.UI.Internals
{
    public abstract class FormulaReference: FormulaToken, INotifyPropertyChanged
    {
        internal FormulaReference(Token t, Formula owner) : base (t){ this._owner = owner; }
        

        protected static CellRelativeAddress GetOffset(NavigationDirection dir)
        {
            switch (dir)
            {
                case NavigationDirection.Down:
                    return new CellRelativeAddress(1, 0);
                case NavigationDirection.Up:
                    return new CellRelativeAddress(-1, 0);
                case NavigationDirection.Left:
                    return new CellRelativeAddress(0, -1);
                case NavigationDirection.Right:
                    return new CellRelativeAddress(0, 1);
                default:
                    throw new NotSupportedException();
            }
        }

        protected void NotifyChanged()
        {
            notifyPropertyChanged("Row");
            notifyPropertyChanged("Column");
            notifyPropertyChanged("RowSpan");
            notifyPropertyChanged("ColumnSpan");
            notifyPropertyChanged("IsFullRow");
            notifyPropertyChanged("IsFullColumn");
            notifyPropertyChanged("Label");
        }

        public abstract Worksheet Worksheet { get; }
        readonly Formula _owner;
        public int Row
        {
            get { return TopLeft.Row.Index; }
        }
        public int Column
        { get { return TopLeft.Column.Index; } }

        protected abstract Cell TopLeft { get; }

        public abstract int RowSpan { get; }

        public abstract int ColumnSpan { get; }
        public int Index { get { return _owner.References.IndexOf(this); } }
        public abstract bool IsFullRow { get; }
        public abstract bool IsFullColumn { get; }

        protected abstract string Label
        { get;
        }
        public string FullLabel
        {
            get
            {
                if (Worksheet != this._owner.Worksheet)
                    return Worksheet.SafeName + "!" + Label;
                return Label;
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;
        void notifyPropertyChanged(string propertyName)
        {
            Contract.Requires(GetType().GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic) != null);
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }

        #endregion

        internal abstract RangeAddress AsRangeAddress();

        internal abstract void Move(CellRelativeAddress address);
        internal abstract void Extend(CellAddress address, ResizerType type);

        internal abstract void Move(NavigationDirection navigationDirection, bool hold);

        public abstract void ToggleLock();
    }
}